function [cost, results] = FitnessFunc_CBonly(x, mpc, P_loss0, V_dev0) 
%% 阶段1适应度：仅优化 CB 台数（SVG 禁止介入）
% 约束：Q 不倒送；PCC PF ∈ [0.89, 0.91]；电压不越限
% 说明：
% - mpc.cb(:,2) 应为“pu步长”（相对 baseMVA）；每步无功 = cb(:,2) * baseMVA (Mvar)

%% 参数（阶段一目标）
pf_lo       = 0.89;      % PF 下限（给 SVG 留余量）
pf_hi       = 0.91;      % PF 上限（避免过补）
P_deadband  = 0.00;      % 建议0：双向都考核；如需近零放宽可设 0.02

% 约束/权重
enforce_no_Q_export  = true;   % 禁止倒送无功（Q_pcc < 0）
Q_export_tol         = 0.02;   % Mvar 允许的微小负值容差
limit_local_overcomp = true;   % 本地不过补
cb_keep_ratio_of_Qd  = 0.05;   % 负荷点至少保留 5% 感性无功
alpha1 = 0.7; alpha2 = 0.3;    % 网损/电压偏差权重
vmax_hi = 1.05; vmax_lo = 0.95;

%% 解码 CB 台数（3/4/5维兼容）
n = numel(x);
if     n >= 5, idx = [3,4,5];   % [ESS, SVC, CB2, CB3, CB4]
elseif n == 4, idx = [2,3,4];   % [ESS,      CB2, CB3, CB4]
elseif n == 3, idx = [1,2,3];   % [          CB2, CB3, CB4]
else
    error('x 维度不对：期望 3/4/5，实际 %d', n);
end

CB_steps = zeros(3,1);
for i = 1:3
    CB_steps(i) = min(mpc.cb(i,3), max(0, round(x(idx(i)) * mpc.cb(i,3))));
end

%% 投 CB：严格“整数台数 × 步长”
Qstep_Mvar = mpc.cb(:,2) * mpc.baseMVA;   % 每步 Mvar（cb(:,2) 为 pu）
m = mpc; 
Q_cb_applied = zeros(3,1);

for i = 1:3
    bi    = mpc.cb(i,1);
    Qd0   = mpc.bus(bi,4);        % 原始无功负荷 (Mvar)
    stepM = Qstep_Mvar(i);
    req_steps = CB_steps(i);

    % 不过补保留：最多抵消到 (1 - keep_ratio) * Qd0
    Qd_floor = 0;
    if limit_local_overcomp
        Qd_floor = cb_keep_ratio_of_Qd * max(Qd0, 0);
    end
    Q_allow       = max(Qd0 - Qd_floor, 0);
    allow_steps   = floor(Q_allow/stepM + 1e-9);
    applied_steps = min(req_steps, allow_steps);

    Qcb = applied_steps * stepM;
    Q_cb_applied(i) = Qcb;
    m.bus(bi,4) = Qd0 - Qcb;      % 更新该负荷母线的无功
end

% 阶段1禁 SVG：固定 SVG 无功 = 0
if isfield(m,'svg') && isfield(m.svg,'gen_idx') && ~isempty(m.svg.gen_idx)
    gidx = m.svg.gen_idx;
    m.gen(gidx,3) = 0;  % Qg
    m.gen(gidx,4) = 0;  % Qmax
    m.gen(gidx,5) = 0;  % Qmin
end

%% 潮流
try
    r = runpf(m);
    if ~r.success, error('PF 不收敛'); end
catch
    cost = 1e6; 
    results = fail_result(CB_steps, Q_cb_applied);
    return;
end

%% 指标/约束
[P, Q, pf] = slackPQPF(r);
pf_abs = abs(pf);
V = r.bus(:,8);

% 电压越限罚
v_violation = sum(max(0, V - vmax_hi)) + sum(max(0, vmax_lo - V));
penalty = 300 * v_violation;

% 禁止倒送无功（容性为负）
if enforce_no_Q_export && (Q < -Q_export_tol)
    penalty = penalty + 1000 * (-Q - Q_export_tol);
end

% PF 带宽罚（仅当 |P| 大于死区）
if abs(P) > P_deadband
    if pf_abs < pf_lo
        penalty = penalty + 800 * (pf_lo - pf_abs);     % 欠补
    elseif pf_abs > pf_hi
        % PF 过高（过补）；若 Q<0 已被上面的“倒送无功”强罚
        penalty = penalty + 400 * (pf_abs - pf_hi);
    end
end

% 目标项：网损、电压偏差
loss = real(sum(get_losses(r)));
vdev = sum(abs(V - 1.0));

% 归一化，防 0/NaN
if ~isfinite(P_loss0) || P_loss0 <= 0, P_loss0 = max(loss, 1e-6); end
if ~isfinite(V_dev0)  || V_dev0  <= 0, V_dev0  = max(vdev, 1e-6); end
f_loss = loss / P_loss0;
f_vdev = vdev / V_dev0;

% 综合成本
cost = alpha1 * f_loss + alpha2 * f_vdev + penalty;

%% 输出
results = struct();
results.bus     = r.bus;
results.gen     = r.gen;
results.branch  = r.branch;
results.loss    = loss;
results.v_dev   = vdev;
results.P_pcc   = P;
results.Q_pcc   = Q;
results.pf      = pf_abs;
results.CB_steps= CB_steps;
results.Q_cb    = Q_cb_applied;
results.Q_svc   = 0;       % 阶段1不使用 SVG
results.cost    = cost;
end

%% 工具
function R = fail_result(CB_steps, Q_cb_applied)
R = struct('loss',NaN,'v_dev',NaN,'penalty',1e6,'cost',1e6, ...
           'P_pcc',NaN,'Q_pcc',NaN,'pf',NaN, ...
           'CB_steps',CB_steps,'Q_cb',Q_cb_applied,'Q_svc',0);
end

function [P_slack, Q_slack, pf_val] = slackPQPF(res)
sl = (res.gen(:,1)==1); 
P_slack = sum(res.gen(sl,2)); 
Q_slack = sum(res.gen(sl,3));
S = hypot(P_slack, Q_slack); 
if S < 1e-9, pf_val = 1.0; else, pf_val = P_slack / S; end
end
